
`include "common_header.verilog"

//  *************************************************************************
//  File : gearbox66_og1_bp
//  *************************************************************************
//  This program is controlled by a written license agreement.
//  Unauthorized reproduction or use is expressly prohibited. 
//  Copyright (c) 2008 MorethanIP
//  Muenchner Strasse 199, 85757 Karlsfeld, Germany
//  info@morethanip.com
//  http://www.morethanip.com
//  *************************************************************************
//  Designed by : Thomas Schrobenhauser (66:40)
//  Extended by : Muhammad Anisur Rahman (66:32)
//  Extended by : Denis Poverennyy (66:20), (66:66) and clk_ena
//  info@morethanip.com
//  *************************************************************************
//  Decription : General purpose Gearbox for Serdes interfacing.
//  Version    : $Id: gearbox66_og1_bp.v,v 1.7 2012/12/19 15:12:03 dk Exp $
//  *************************************************************************

module gearbox66_og1_bp (

   reset,
   clk,
   clk_ena,
   gb_bp_ena,
   ff_rd,
   ff_din,
   ff_aempty,
   data_out);

parameter SERDES_WIDTH = 20;    // width of serdes output
parameter IN_REGISTER  = 1;     // add input register
parameter OUT_REGISTER = 1;     // add output register

input   reset;          //  async active high reset
input   clk;            //  system clock
input   clk_ena;        //  clock enable
input   gb_bp_ena;      //  bypass enable
output  ff_rd;          //  FIFO read enable
input   [65:0] ff_din;  //  FIFO data input
input   ff_aempty;      //  FIFO almost empty
output  [(SERDES_WIDTH - 1):0] data_out; 


// -----------------------------------
//  System
// -----------------------------------
wire    ff_rd; 
wire    [(SERDES_WIDTH - 1):0] data_out; 
reg     data_rd; 
reg     [65:0] d0; 
reg     [65:0] d1; 
reg     [5:0] cnt; 
reg     [(SERDES_WIDTH - 1):0] mux_out; 

// optional input register
// -----------------------
generate if( IN_REGISTER==1 )
begin:ireg
        always @(posedge reset or posedge clk)
        begin : pireg
                if (reset == 1'b 1)
                begin
                        d0 <= {66{1'b 0}};	
                end
                else
                begin
                    if (clk_ena == 1'b 1)
                    begin
                        d0 <= ff_din;	
                    end
                end
        end
end
else
begin:noireg

        always@(ff_din) d0 = ff_din;

end
endgenerate

//`ifdef EN_SERDES16
generate if( SERDES_WIDTH==16 )
begin:g16

wire    next_rd; 

reg     [65:0] d2; 
reg     [65:0] d3; 
reg     [65:0] d4; 
reg     [5:0] cnt_r; 
reg     [5:0] cnt_r2; 
reg     [5:0] cnt_r3; 

always @(posedge reset or posedge clk)
   begin : process_1
   if (reset == 1'b 1)
      begin
      data_rd <= 1'b 0;
      d1 <= {66{1'b 0}};
      d2 <= {66{1'b 0}};
      d3 <= {66{1'b 0}};
      d4 <= {66{1'b 0}};
      cnt <= {6{1'b 0}};
      cnt_r <= {6{1'b 0}};
      cnt_r2 <= {6{1'b 0}};
      cnt_r3 <= {6{1'b 0}};
      end
   else
      begin
      if (clk_ena == 1'b 1)
         begin
 
         data_rd <= next_rd;
 
         d1 <= d0;
         d2 <= d1;
         d3 <= d2;
         d4 <= d3;

         //  33-cycle counter
         // Bypass forces it to state0 so input is simply copied 1:1
         if (cnt == 6'b 100000 | ff_aempty == 1'b 1 | gb_bp_ena == 1'b 1)
            begin
            cnt <= {6{1'b 0}};
            end
         else if (ff_aempty == 1'b 0 )
            begin
            cnt <= cnt + 6'b 000001;
            end

         cnt_r <= cnt;
         cnt_r2 <= cnt_r;
         cnt_r3 <= cnt_r2;

         end
      end
   end

assign next_rd = ff_aempty == 1'b 0 & (cnt == 6'b 000000 |
                   cnt == 6'b 000100 | cnt == 6'b 001000 |
                   cnt == 6'b 001100 | cnt == 6'b 010000 |
                   cnt == 6'b 010100 | cnt == 6'b 011000 |
                   cnt == 6'b 011100) ? 1'b 1 : 1'b 0;


        always @(cnt_r3 or d0 or d1 or d2 or d3 or d4)
        begin
                
         //  output mux
         case (cnt_r3)
            6'b 000000:
               begin
               mux_out = d0[15:0];
               end
            6'b 000001:
               begin
               mux_out = d1[31:16];
               end
            6'b 000010:
               begin
               mux_out = d2[47:32];
               end
            6'b 000011:
               begin
               mux_out = d3[63:48];
               end
            6'b 000100:
               begin
               mux_out = {d0[13:0], d4[65:64]};
               end
            6'b 000101:
               begin
               mux_out = d1[29:14];
               end
            6'b 000110:
               begin
               mux_out = d2[45:30];
               end
            6'b 000111:
               begin
               mux_out = d3[61:46];
               end
            6'b 001000:
               begin
               mux_out = {d0[11:0], d4[65:62]};
               end
            6'b 001001:
               begin
               mux_out = d1[27:12];
               end
            6'b 001010:
               begin
               mux_out = d2[43:28];
               end
            6'b 001011:
               begin
               mux_out = d3[59:44];
               end
            6'b 001100:
               begin
               mux_out = {d0[9:0], d4[65:60]};
               end
            6'b 001101:
               begin
               mux_out = d1[25:10];
               end
            6'b 001110:
               begin
               mux_out = d2[41:26];
               end
            6'b 001111:
               begin
               mux_out = d3[57:42];
               end
            6'b 010000:
               begin
               mux_out = {d0[7:0], d4[65:58]};
               end
            6'b 010001:
               begin
               mux_out = d1[23:8];
               end
            6'b 010010:
               begin
               mux_out = d2[39:24];
               end
            6'b 010011:
               begin
               mux_out = d3[55:40];
               end
            6'b 010100:
               begin
               mux_out = {d0[5:0], d4[65:56]};
               end
            6'b 010101:
               begin
               mux_out = d1[21:6];
               end
            6'b 010110:
               begin
               mux_out = d2[37:22];
               end
            6'b 010111:
               begin
               mux_out = d3[53:38];
               end
            6'b 011000:
               begin
               mux_out = {d0[3:0], d4[65:54]};
               end
            6'b 011001:
               begin
               mux_out = d1[19:4];
               end
            6'b 011010:
               begin
               mux_out = d2[35:20];
               end
            6'b 011011:
               begin
               mux_out = d3[51:36];
               end
            6'b 011100:
               begin
               mux_out = {d0[1:0], d4[65:52]};
               end
            6'b 011101:
               begin
               mux_out = d1[17:2];
               end
            6'b 011110:
               begin
               mux_out = d2[33:18];
               end
            6'b 011111:
               begin
               mux_out = d3[49:34];
               end
            6'b 100000:
               begin
               mux_out = d4[65:50];
               end
            default:
               begin
               mux_out = {(SERDES_WIDTH){1'b 0}};
               end
            endcase

        end
end
endgenerate
//`endif

// `ifdef EN_SERDES20
generate if( SERDES_WIDTH==20 )
begin:g20
 
wire    next_rd; 

reg     [65:0] d2; 
reg     [65:0] d3; 
reg     [65:0] d4; 
reg     [5:0] cnt_r; 
reg     [5:0] cnt_r2; 
reg     [5:0] cnt_r3; 

always @(posedge reset or posedge clk)
   begin : process_1
   if (reset == 1'b 1)
      begin
      data_rd <= 1'b 0;	
      d1 <= {66{1'b 0}};	
      d2 <= {66{1'b 0}};	
      d3 <= {66{1'b 0}};	
      d4 <= {66{1'b 0}};	
      cnt <= {6{1'b 0}};	
      cnt_r <= {6{1'b 0}};	
      cnt_r2 <= {6{1'b 0}};	
      cnt_r3 <= {6{1'b 0}};	
      end
   else
      begin
      if (clk_ena == 1'b 1)
         begin
         
         data_rd <= next_rd;	

         d1 <= d0;	
         d2 <= d1;	
         d3 <= d2;	
         d4 <= d3;	

         //  33-cycle counter
         // Bypass forces it to state0 so input is simply copied 1:1
         if (cnt == 6'b 100000 | ff_aempty == 1'b 1 | gb_bp_ena == 1'b 1)
            begin
            cnt <= {6{1'b 0}};	
            end
         else if (ff_aempty == 1'b 0 )
            begin
            cnt <= cnt + 6'b 000001;	
            end
         cnt_r <= cnt;	
         cnt_r2 <= cnt_r;	
         cnt_r3 <= cnt_r2;	

         end
      end
   end

        assign next_rd = ff_aempty == 1'b 0 & (cnt == 6'b 000000 | 
        	cnt == 6'b 000011 | cnt == 6'b 000110 | 
        	cnt == 6'b 001001 | cnt == 6'b 001101 | 
        	cnt == 6'b 010000 | cnt == 6'b 010011 | 
        	cnt == 6'b 010111 | cnt == 6'b 011010 | 
        	cnt == 6'b 011101) ? 1'b 1 : 
        	1'b 0; 

        always @(cnt_r3 or d0 or d1 or d2 or d3 or d4)
        begin:OMUX_COMB
        
         //  output mux
            case (cnt_r3)
            6'b 000000:
               begin
               mux_out = d0[19:0];	//  20
               end
            6'b 000001:
               begin
               mux_out = d1[39:20];	//  20
               end
            6'b 000010:
               begin
               mux_out = d2[59:40];	//  20
               end
            6'b 000011:
               begin
               mux_out = {d0[13:0], d3[65:60]}; //  14 +  6
               end
            6'b 000100:
               begin
               mux_out = d1[33:14];	//  20
               end
            6'b 000101:
               begin
               mux_out = d2[53:34];	//  20
               end
            6'b 000110:
               begin
               mux_out = {d0[7:0], d3[65:54]};	//   8 + 12
               end
            6'b 000111:
               begin
               mux_out = d1[27:8];	//  20
               end
            6'b 001000:
               begin
               mux_out = d2[47:28];	//  20
               end
            6'b 001001:
               begin
               mux_out = {d0[1:0], d3[65:48]};	//   2 + 18
               end
            6'b 001010:
               begin
               mux_out = d1[21:2];	//  20
               end
            6'b 001011:
               begin
               mux_out = d2[41:22];	//  20
               end
            6'b 001100:
               begin
               mux_out = d3[61:42];	//  20
               end
            6'b 001101:
               begin
               mux_out = {d0[15:0], d4[65:62]}; //  16 +  4
               end
            6'b 001110:
               begin
               mux_out = d1[35:16];	//  20
               end
            6'b 001111:
               begin
               mux_out = d2[55:36];	//  20
               end
            6'b 010000:
               begin
               mux_out = {d0[9:0], d3[65:56]};	//  10 + 10
               end
            6'b 010001:
               begin
               mux_out = d1[29:10];	//  20
               end
            6'b 010010:
               begin
               mux_out = d2[49:30];	//  20
               end
            6'b 010011:
               begin
               mux_out = {d0[3:0], d3[65:50]};	//   4 + 16
               end
            6'b 010100:
               begin
               mux_out = d1[23:4];	//  20
               end
            6'b 010101:
               begin
               mux_out = d2[43:24];	//  20
               end
            6'b 010110:
               begin
               mux_out = d3[63:44];	//  20
               end
            6'b 010111:
               begin
               mux_out = {d0[17:0], d4[65:64]}; //  18 +  2
               end
            6'b 011000:
               begin
               mux_out = d1[37:18];	//  20
               end
            6'b 011001:
               begin
               mux_out = d2[57:38];	//  20
               end
            6'b 011010:
               begin
               mux_out = {d0[11:0], d3[65:58]}; //  12 +  8
               end
            6'b 011011:
               begin
               mux_out = d1[31:12];	//  20
               end
            6'b 011100:
               begin
               mux_out = d2[51:32];	//  20
               end
            6'b 011101:
               begin
               mux_out = {d0[5:0], d3[65:52]};	//   6 + 14
               end
            6'b 011110:
               begin
               mux_out = d1[25:6];	//  20
               end
            6'b 011111:
               begin
               mux_out = d2[45:26];	//  20
               end
            6'b 100000:
               begin
               mux_out = d3[65:46];	//  20
               end
            default:
               begin
               mux_out = {20{1'b 0}};	
               end
            endcase

        end




end
endgenerate
//`endif

//`ifdef EN_SERDES40
generate if( SERDES_WIDTH==40 )
begin:g40

wire    next_rd; 
reg     [65:0] d2; 
reg     [5:0] cnt_r; 
reg     [5:0] cnt_r2; 
reg     [5:0] cnt_r3; 


always @(posedge reset or posedge clk)
   begin : process_1
   if (reset == 1'b 1)
      begin
      data_rd <= 1'b 0;	
      d1 <= {66{1'b 0}};	
      d2 <= {66{1'b 0}};	
      cnt <= {6{1'b 0}};	
      cnt_r <= {6{1'b 0}};	
      cnt_r2 <= {6{1'b 0}};	
      cnt_r3 <= {6{1'b 0}};	
      end
   else
      if (clk_ena == 1'b 1)
      begin
      data_rd <= next_rd;	
      d1 <= d0;	
      d2 <= d1;	
//  33-cycle counter
      if (cnt == 6'b 100000 |  ff_aempty == 1'b 1 | gb_bp_ena == 1'b 1)
         begin
         cnt <= {6{1'b 0}};	
         end
      else if (ff_aempty == 1'b 0 )
         begin
         cnt <= cnt + 6'b 000001;	
         end
      cnt_r <= cnt;	
      cnt_r2 <= cnt_r;	
      
      if( ff_aempty==1'b 1 )
        begin
        cnt_r3 <= 6'd 33;  // force zero output while FIFO has no data (e.g. during sw-reset).
        end
      else
        begin
        cnt_r3 <= cnt_r2;	
        end
        
      end
   end

        assign next_rd = ff_aempty == 1'b 1 | cnt == 6'b 000010 | 
        	cnt == 6'b 000101 | cnt == 6'b 000111 | 
        	cnt == 6'b 001010 | cnt == 6'b 001100 | 
        	cnt == 6'b 001111 | cnt == 6'b 010001 | 
        	cnt == 6'b 010100 | cnt == 6'b 010110 | 
        	cnt == 6'b 011001 | cnt == 6'b 011011 | 
        	cnt == 6'b 011110 | cnt == 6'b 100000 ? 1'b 0 : 
        	1'b 1; 
        
        //  output mux
        always @(cnt_r3 or d0 or d1 or d2)
        begin
                case (cnt_r3)
                6'b 000000:
                   begin
                   mux_out = d0[39:0];	//  40
                   end
                6'b 000001:
                   begin
                   mux_out = {d0[13:0], d1[65:40]};	//  14 + 26
                   end
                6'b 000010:
                   begin
                   mux_out = d1[53:14];	//  40
                   end
                6'b 000011:
                   begin
                   mux_out = {d0[27:0], d2[65:54]};	//  28 + 12
                   end
                6'b 000100:
                   begin
                   mux_out = {d0[1:0], d1[65:28]};	//   2 + 38
                   end
                6'b 000101:
                   begin
                   mux_out = d1[41:2];	//  40
                   end
                6'b 000110:
                   begin
                   mux_out = {d0[15:0], d2[65:42]};	//  16 + 24
                   end
                6'b 000111:
                   begin
                   mux_out = d1[55:16];	//  40
                   end
                6'b 001000:
                   begin
                   mux_out = {d0[29:0], d2[65:56]};	//  30 + 10
                   end
                6'b 001001:
                   begin
                   mux_out = {d0[3:0], d1[65:30]};	//   4 + 36
                   end
                6'b 001010:
                   begin
                   mux_out = d1[43:4];	//  40
                   end
                6'b 001011:
                   begin
                   mux_out = {d0[17:0], d2[65:44]};	//  18 + 22
                   end
                6'b 001100:
                   begin
                   mux_out = d1[57:18];	//  40
                   end
                6'b 001101:
                   begin
                   mux_out = {d0[31:0], d2[65:58]};	//  32 +  8
                   end
                6'b 001110:
                   begin
                   mux_out = {d0[5:0], d1[65:32]};	//   6 + 34
                   end
                6'b 001111:
                   begin
                   mux_out = d1[45:6];	//  40
                   end
                6'b 010000:
                   begin
                   mux_out = {d0[19:0], d2[65:46]};	//  20 + 20
                   end
                6'b 010001:
                   begin
                   mux_out = d1[59:20];	//  40
                   end
                6'b 010010:
                   begin
                   mux_out = {d0[33:0], d2[65:60]};	//  34 +  6
                   end
                6'b 010011:
                   begin
                   mux_out = {d0[7:0], d1[65:34]};	//   8 + 32
                   end
                6'b 010100:
                   begin
                   mux_out = d1[47:8];	//  40
                   end
                6'b 010101:
                   begin
                   mux_out = {d0[21:0], d2[65:48]};	//  22 + 18
                   end
                6'b 010110:
                   begin
                   mux_out = d1[61:22];	//  40
                   end
                6'b 010111:
                   begin
                   mux_out = {d0[35:0], d2[65:62]};	//  36 +  4
                   end
                6'b 011000:
                   begin
                   mux_out = {d0[9:0], d1[65:36]};	//  10 + 30
                   end
                6'b 011001:
                   begin
                   mux_out = d1[49:10];	//  40
                   end
                6'b 011010:
                   begin
                   mux_out = {d0[23:0], d2[65:50]};	//  24 + 16
                   end
                6'b 011011:
                   begin
                   mux_out = d1[63:24];	//  40
                   end
                6'b 011100:
                   begin
                   mux_out = {d0[37:0], d2[65:64]};	//  38 +  2
                   end
                6'b 011101:
                   begin
                   mux_out = {d0[11:0], d1[65:38]};	//  12 + 28
                   end
                6'b 011110:
                   begin
                   mux_out = d1[51:12];	//  40
                   end
                6'b 011111:
                   begin
                   mux_out = {d0[25:0], d2[65:52]};	//  26 + 14
                   end
                6'b 100000:
                   begin
                   mux_out = d1[65:26];	//  40
                   end
                default:
                   begin
                   mux_out = {40{1'b 0}};	
                   end
                endcase
        end
end
endgenerate
//`endif


//`ifdef EN_SERDES32
generate if( SERDES_WIDTH==32 )
begin:g32

reg     [5:0] cnt_r; 

always @(posedge reset or posedge clk)
   begin : process_32
   if (reset == 1'b 1)
      begin
      data_rd <= 1'b 0;	
      d1 <= {66{1'b 0}};	
      cnt <= {6{1'b 0}};	
      cnt_r <= {6{1'b 0}};	
      end
   else
      begin
      if (clk_ena == 1'b 1)
      begin
      if (ff_aempty==1'b 0 & ((gb_bp_ena==1'b 0 & cnt[0] == 1'b 1) | gb_bp_ena==1'b 1) )
         begin
         data_rd <= 1'b 1;	
         end
      else
         begin
         data_rd <= 1'b 0;	
         end

      d1 <= d0;	

      if ( gb_bp_ena == 1'b 1 )
         begin
           // Bypass forces copy 1:1. Above data_rd will be 1 always
         cnt <= 6'b 000011;
         end
      else if (cnt == 6'b 100000 |  ff_aempty == 1'b 1)
         begin
         cnt <= {6{1'b 0}};	
         end
      else if (ff_aempty == 1'b 0 )
         begin
         cnt <= cnt + 6'b 000001;	
         end

        cnt_r <= cnt;

      end
     end
   end

        always@( cnt_r or d0 or d1 )
        begin
                case (cnt_r)
                6'b 000000:
                   begin
                   mux_out = {d0[1:0], d1[65:36]};	
                   end
                6'b 000001:
                   begin
                   mux_out = d0[33:2];	
                   end
                6'b 000010:
                   begin
                   mux_out = d1[65:34];	
                   end
                6'b 000011:
                   begin
                   mux_out = d0[31:0];	
                   end
                6'b 000100:
                   begin
                   mux_out = d0[63:32];	
                   end
                6'b 000101:
                   begin
                   mux_out = {d0[29:0], d1[65:64]};	
                   end
                6'b 000110:
                   begin
                   mux_out = d0[61:30];	
                   end
                6'b 000111:
                   begin
                   mux_out = {d0[27:0], d1[65:62]};	
                   end
                6'b 001000:
                   begin
                   mux_out = d0[59:28];	
                   end
                6'b 001001:
                   begin
                   mux_out = {d0[25:0], d1[65:60]};	
                   end
                6'b 001010:
                   begin
                   mux_out = d0[57:26];	
                   end
                6'b 001011:
                   begin
                   mux_out = {d0[23:0], d1[65:58]};	
                   end
                6'b 001100:
                   begin
                   mux_out = d0[55:24];	
                   end
                6'b 001101:
                   begin
                   mux_out = {d0[21:0], d1[65:56]};	
                   end
                6'b 001110:
                   begin
                   mux_out = d0[53:22];	
                   end
                6'b 001111:
                   begin
                   mux_out = {d0[19:0], d1[65:54]};	
                   end
                6'b 010000:
                   begin
                   mux_out = d0[51:20];	
                   end
                6'b 010001:
                   begin
                   mux_out = {d0[17:0], d1[65:52]};	
                   end
                6'b 010010:
                   begin
                   mux_out = d0[49:18];	
                   end
                6'b 010011:
                   begin
                   mux_out = {d0[15:0], d1[65:50]};	
                   end
                6'b 010100:
                   begin
                   mux_out = d0[47:16];	
                   end
                6'b 010101:
                   begin
                   mux_out = {d0[13:0], d1[65:48]};	
                   end
                6'b 010110:
                   begin
                   mux_out = d0[45:14];	
                   end
                6'b 010111:
                   begin
                   mux_out = {d0[11:0], d1[65:46]};	
                   end
                6'b 011000:
                   begin
                   mux_out = d0[43:12];	
                   end
                6'b 011001:
                   begin
                   mux_out = {d0[9:0], d1[65:44]};	
                   end
                6'b 011010:
                   begin
                   mux_out = d0[41:10];	
                   end
                6'b 011011:
                   begin
                   mux_out = {d0[7:0], d1[65:42]};	
                   end
                6'b 011100:
                   begin
                   mux_out = d0[39:8];	
                   end
                6'b 011101:
                   begin
                   mux_out = {d0[5:0], d1[65:40]};	
                   end
                6'b 011110:
                   begin
                   mux_out = d0[37:6];	
                   end
                6'b 011111:
                   begin
                   mux_out = {d0[3:0], d1[65:38]};	
                   end
                6'b 100000:
                   begin
                   mux_out = d0[35:4];	
                   end
                default:
                   begin
                   mux_out = {32{1'b 0}};	
                   end
                endcase
        end
end
endgenerate
//`endif


//`ifdef EN_SERDES64
generate if( SERDES_WIDTH==64 )
begin:g64

always @(posedge reset or posedge clk)
   begin : process_1
   if (reset == 1'b 1)
      begin
      data_rd <= 1'b 0;
      d1 <= {66{1'b 0}};
      cnt <= {6{1'b 0}};
      end
   else
      begin
      if (clk_ena == 1'b 1)
        begin
        if (ff_aempty == 1'b 1 | (gb_bp_ena == 1'b 0 & cnt == 6'b 011101))
           begin
           data_rd <= 1'b 0;
           end
        else
           begin
           data_rd <= 1'b 1;
           end

        d1 <= d0;

        if (cnt == 6'b 100000 | ff_aempty == 1'b 1 | gb_bp_ena == 1'b 1)
           begin
           cnt <= {6{1'b 0}};
           end
        else if (ff_aempty == 1'b 0 )
           begin
           cnt <= cnt + 6'b 000001;
           end

        end
      end
   end

        always @(cnt or d0 or d1)
        begin

                case (cnt)
                6'b 000000:
                   begin
                   mux_out = d0[63:0];
                   end
                6'b 000001:
                   begin
                   mux_out = {d0[61:0], d1[65:64]};
                   end
                6'b 000010:
                   begin
                   mux_out = {d0[59:0], d1[65:62]};
                   end
                6'b 000011:
                   begin
                   mux_out = {d0[57:0], d1[65:60]};
                   end
                6'b 000100:
                   begin
                   mux_out = {d0[55:0], d1[65:58]};
                   end
                6'b 000101:
                   begin
                   mux_out = {d0[53:0], d1[65:56]};
                   end
                6'b 000110:
                   begin
                   mux_out = {d0[51:0], d1[65:54]};
                   end
                6'b 000111:
                   begin
                   mux_out = {d0[49:0], d1[65:52]};
                   end
                6'b 001000:
                   begin
                   mux_out = {d0[47:0], d1[65:50]};
                   end
                6'b 001001:
                   begin
                   mux_out = {d0[45:0], d1[65:48]};
                   end
                6'b 001010:
                   begin
                   mux_out = {d0[43:0], d1[65:46]};
                   end
                6'b 001011:
                   begin
                   mux_out = {d0[41:0], d1[65:44]};
                   end
                6'b 001100:
                   begin
                   mux_out = {d0[39:0], d1[65:42]};
                   end
                6'b 001101:
                   begin
                   mux_out = {d0[37:0], d1[65:40]};
                   end
                6'b 001110:
                   begin
                   mux_out = {d0[35:0], d1[65:38]};
                   end
                6'b 001111:
                   begin
                   mux_out = {d0[33:0], d1[65:36]};
                   end
                6'b 010000:
                   begin
                   mux_out = {d0[31:0], d1[65:34]};
                   end
                6'b 010001:
                   begin
                   mux_out = {d0[29:0], d1[65:32]};
                   end
                6'b 010010:
                   begin
                   mux_out = {d0[27:0], d1[65:30]};
                   end
                6'b 010011:
                   begin
                   mux_out = {d0[25:0], d1[65:28]};
                   end
                6'b 010100:
                   begin
                   mux_out = {d0[23:0], d1[65:26]};
                   end
                6'b 010101:
                   begin
                   mux_out = {d0[21:0], d1[65:24]};
                   end
                6'b 010110:
                   begin
                   mux_out = {d0[19:0], d1[65:22]};
                   end
                6'b 010111:
                   begin
                   mux_out = {d0[17:0], d1[65:20]};
                   end
                6'b 011000:
                   begin
                   mux_out = {d0[15:0], d1[65:18]};
                   end
                6'b 011001:
                   begin
                   mux_out = {d0[13:0], d1[65:16]};
                   end
                6'b 011010:
                   begin
                   mux_out = {d0[11:0], d1[65:14]};
                   end
                6'b 011011:
                   begin
                   mux_out = {d0[9:0], d1[65:12]};
                   end
                6'b 011100:
                   begin
                   mux_out = {d0[7:0], d1[65:10]};
                   end
                6'b 011101:
                   begin
                   mux_out = {d0[5:0], d1[65:8]};
                   end
                6'b 011110:
                   begin
                   mux_out = {d0[3:0], d1[65:6]};
                   end
                6'b 011111:
                   begin
                   mux_out = {d0[1:0], d1[65:4]};
                   end
                6'b 100000:
                   begin
                   mux_out = d1[65:2];
                   end
                default:
                   begin
                   mux_out = {64{1'b 0}};
                   end
                endcase

        end
end
endgenerate
//`endif


//`ifdef EN_SERDES66
generate if( SERDES_WIDTH==66 )
begin:g66
 
always @(ff_aempty) data_rd = ~ff_aempty;

always @(d0)    mux_out = d0;

end
endgenerate
//`endif


assign ff_rd = data_rd; 

// ------------------------
// optional output register
// ------------------------
generate if( OUT_REGISTER==1 )
begin:goreg

        reg     [(SERDES_WIDTH - 1):0] mux_out_r; 
        
        always@( posedge reset or posedge clk )
        begin:p_oreg
                if( reset==1'b 1 )
                begin
                        mux_out_r <= {SERDES_WIDTH{1'b 0}};
                end
                else if( clk_ena == 1'b 1 )
                begin
                        mux_out_r <= mux_out;                        
                end
        end
   
        assign data_out = mux_out_r;
        
end
else
begin:gnooreg
        
        assign data_out = mux_out; 

end
endgenerate
       
    


endmodule 

